using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Patterns.Tools.CodeGenerators.GoogleCode
{
	public static class WikiNames
	{
		public static class Sidebar
		{
			public static string SidebarDisplay(string name)
			{
				var pattern = new Regex(@"(?<name>[^_]+)(_(?<num>\d+))?$");
				return GetDisplayName(name, pattern);
			}
		}

		private const string _singleArg = "T";
		private const string _upToThree = "XYZ";
		private const string _overThree = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

		public static string Get(Type objectType)
		{
			var name = objectType.FullName;
			if (objectType.IsEnum) return Enum(name);
			return objectType.IsInterface ? Interface(name) : Class(name);
		}

		public static string Class(string name)
		{
			return Clean(string.Format("class_{0}", name.Replace(".", "_")));
		}

		public static string Interface(string name)
		{
			return Clean(string.Format("interface_{0}", name.Replace(".", "_")));
		}

		public static string Enum(string name)
		{
			return string.Format("enum_{0}", name.Replace(".", "_"));
		}

		public static string Assembly(string name)
		{
			return string.Format("assembly_{0}", name.Replace(".", "_"));
		}

		public static string Namespace(string name)
		{
			return string.Format("namespace_{0}", name.Replace(".", "_"));
		}

		public static string Clean(string name)
		{
			return name.Trim('`').Replace("`", "_");
		}

		public static string Display(string name)
		{
			var pattern = new Regex(@"(?<name>[^`\.]+)(`(?<num>\d+))?");
			return GetDisplayName(name, pattern);
		}

		private static string GetDisplayName(string name, Regex pattern)
		{
			var match = pattern.Match(name);
			if (!match.Success) return name;
			var numCapture = match.Groups["num"];
			var friendlyName = match.Groups["name"].Value;
			return numCapture.Success
			       	? string.Format("{0}<{1}>", friendlyName, GetTypeArgs(Convert.ToInt32(numCapture.Value)))
			       	: friendlyName;
		}

		private static string GetTypeArgs(int argCount)
		{
			return string.Join(",", GetTypeArgSet(argCount));
		}

		private static IEnumerable<char> GetTypeArgSet(int argCount)
		{
			string argString = GetArgString(argCount);
			for (int index = 0; index < argCount; index++) yield return argString[index];
		}

		private static string GetArgString(int argCount)
		{
			if (argCount == 1) return _singleArg;
			return argCount < 4 ? _upToThree : _overThree;
		}
	}
}